#include "StdAfx.h"
#include "Tracker.h"

int CTracker::kTolerance    = 6;
int CTracker::kLineDelta    = 1;
int CTracker::kPageDelta	  = 5;
int CTracker::kArrowHeight  = 2;
int CTracker::kArrowWidth	  = 1;
int CTracker::kMarkerSize	  = 10;
int CTracker::kHandleSize   = 7;
int CTracker::kBorderWidth  = 1;

const HCURSOR CTracker::kSizeWE		= ::LoadCursor(NULL, IDC_SIZEWE);
const HCURSOR CTracker::kSizeNESW	= ::LoadCursor(NULL, IDC_SIZENESW);
const HCURSOR CTracker::kSizeNS		= ::LoadCursor(NULL, IDC_SIZENS);
const HCURSOR CTracker::kSizeNWSE	= ::LoadCursor(NULL, IDC_SIZENWSE);
const HCURSOR CTracker::kSizeAll	= ::LoadCursor(NULL, IDC_SIZEALL);

const HCURSOR CTracker::kBorderCursors[8]	= {kSizeWE, kSizeNESW, kSizeNS,
  kSizeNWSE, kSizeWE, kSizeNESW, kSizeNS, kSizeNWSE};

const geometry::Vector2D CTracker::kVector[8] = {
  geometry::Vector2D( 0.9238795325113,  0.3826834323651),
  geometry::Vector2D( 0.3826834323651,  0.9238795325113),
  geometry::Vector2D(-0.3826834323651,  0.9238795325113),
  geometry::Vector2D(-0.9238795325113,  0.3826834323651),
  geometry::Vector2D(-0.9238795325113, -0.3826834323651),
  geometry::Vector2D(-0.3826834323651, -0.9238795325113),
  geometry::Vector2D( 0.3826834323651, -0.9238795325113),
  geometry::Vector2D( 0.9238795325113, -0.3826834323651)};

CTracker::CTracker(void)
{
  border_color_   = RGB(0x00, 0x00, 0xFF);
  handle_color_   = RGB(0xFF, 0x00, 0x00);

  visible_        = false;
  title_visible_  = false;
  selected_       = false;
  tracking_       = false;
  frozen_         = false;
  min_size_       = geometry::Size2D(10, 10);
  anchor_         = geometry::Point2D(0, 0);
  pin_            = geometry::Point2D(0, 0);
  bounding_box_   = geometry::Rect2D(0, 0, 0, 0);
}


CTracker::~CTracker(void)
{
}

void CTracker::InflateRect( geometry::Point2D (&vertexes)[4], double width,
  double height, double dx, double dy )
{
  if(width != 0) {
    double tw = dx/width;
    double th = dy/width;
    geometry::Point2D Vl(vertexes[3].y()-vertexes[0].y(),
      vertexes[0].x()-vertexes[3].x());

    geometry::Point2D points[8];
    points[0].set_x(vertexes[0].x()+th*Vl.x());
    points[0].set_y(vertexes[0].y()+th*Vl.y());
    points[1].set_x((1+tw)*vertexes[0].x()-tw*vertexes[3].x());
    points[1].set_y((1+tw)*vertexes[0].y()-tw*vertexes[3].y());
    points[2].set_x((1+tw)*vertexes[1].x()-tw*vertexes[2].x());
    points[2].set_y((1+tw)*vertexes[1].y()-tw*vertexes[2].y());
    points[3].set_x(vertexes[1].x()-th*Vl.x());
    points[3].set_y(vertexes[1].y()-th*Vl.y());
    points[4].set_x(vertexes[2].x()-th*Vl.x());
    points[4].set_y(vertexes[2].y()-th*Vl.y());
    points[5].set_x((1+tw)*vertexes[2].x()-tw*vertexes[1].x());
    points[5].set_y((1+tw)*vertexes[2].y()-tw*vertexes[1].y());
    points[6].set_x((1+tw)*vertexes[3].x()-tw*vertexes[0].x());
    points[6].set_y((1+tw)*vertexes[3].y()-tw*vertexes[0].y());
    points[7].set_x(vertexes[3].x()+th*Vl.x());
    points[7].set_y(vertexes[3].y()+th*Vl.y());

    vertexes[0].set_x((1+tw)*points[0].x()-tw*points[7].x());
    vertexes[0].set_y(points[1].y()+th*Vl.y());

    vertexes[1].set_x((1+tw)*points[3].x()-tw*points[4].x());
    vertexes[1].set_y(points[2].y()-th*Vl.y());

    vertexes[2].set_x((1+tw)*points[4].x()-tw*points[3].x());
    vertexes[2].set_y(points[5].y()-th*Vl.y());

    vertexes[3].set_x((1+tw)*points[7].x()-tw*points[0].x());
    vertexes[3].set_y(points[6].y()+th*Vl.y());
  } else if(height != 0.f) {
    double tw = dx/height;
    double th = dy/height;
    geometry::Point2D Vl(vertexes[0].y()-vertexes[1].y(),
      vertexes[1].x()-vertexes[0].x());

    geometry::Point2D points[8];
    points[0].set_x((1+th)*vertexes[0].x()-th*vertexes[1].x());
    points[0].set_y((1+th)*vertexes[0].y()-th*vertexes[1].y());
    points[1].set_x(vertexes[0].x()+tw*Vl.x());
    points[1].set_y(vertexes[0].y()+tw*Vl.y());
    points[2].set_x(vertexes[1].x()+tw*Vl.x());
    points[2].set_y(vertexes[1].y()+tw*Vl.y());
    points[3].set_x((1+th)*vertexes[1].x()-th*vertexes[0].x());
    points[3].set_y((1+th)*vertexes[1].y()-th*vertexes[0].y());
    points[4].set_x((1+th)*vertexes[2].x()-th*vertexes[3].x());
    points[4].set_y((1+th)*vertexes[2].y()-th*vertexes[3].y());
    points[5].set_x(vertexes[2].x()-tw*Vl.x());
    points[5].set_y(vertexes[2].y()-tw*Vl.y());
    points[6].set_x(vertexes[3].x()-tw*Vl.x());
    points[6].set_y(vertexes[3].y()-tw*Vl.y());
    points[7].set_x((1+th)*vertexes[3].x()-th*vertexes[2].x());
    points[7].set_y((1+th)*vertexes[3].y()-th*vertexes[2].y());

    vertexes[0].set_x(points[0].x()+tw*Vl.x());
    vertexes[0].set_y((1+th)*points[1].y()-th*points[2].y());

    vertexes[1].set_x(points[3].x()+tw*Vl.x());
    vertexes[1].set_y((1+th)*points[2].y()-th*points[1].y());

    vertexes[2].set_x(points[4].x()-tw*Vl.x());
    vertexes[2].set_y((1+th)*points[5].y()-th*points[6].y());

    vertexes[3].set_x(points[7].x()-tw*Vl.x());
    vertexes[3].set_y((1+th)*points[6].y()-th*points[5].y());
  } else {
    vertexes[0].set_x(vertexes[0].x() - dx);
    vertexes[0].set_y(vertexes[0].y() - dy);
    vertexes[1].set_x(vertexes[1].x() - dx);
    vertexes[1].set_y(vertexes[1].y() + dy);
    vertexes[2].set_x(vertexes[2].x() + dx);
    vertexes[2].set_y(vertexes[2].y() + dy);
    vertexes[3].set_x(vertexes[3].x() + dx);
    vertexes[3].set_y(vertexes[3].y() - dy);
  }
}

CTracker::QuadrantCode CTracker::Quadrant(const geometry::Point2D& origin,
  const geometry::Point2D& point)
{
  geometry::Vector2D vt(point.x()-origin.x(), origin.y()-point.y());
  bool bFirst = vt.IsLeft(kVector[7]);
  bool bLast	= vt.IsLeft(kVector[0]);

  if(bFirst && !bLast) {
    return kQuadrantI;
  }

  bFirst = bLast;
  bLast = vt.IsLeft(kVector[1]);
  if(bFirst && !bLast) {
    return kQuadrantII;
  }

  bFirst = bLast;
  bLast = vt.IsLeft(kVector[2]);
  if(bFirst && !bLast) {
    return kQuadrantIII;
  }

  bFirst = bLast;
  bLast = vt.IsLeft(kVector[3]);
  if(bFirst && !bLast) {
    return kQuadrantIV;
  }

  bFirst = bLast;
  bLast = vt.IsLeft(kVector[4]);
  if(bFirst && !bLast) {
    return kQuadrantV;
  }

  bFirst = bLast;
  bLast = vt.IsLeft(kVector[5]);
  if(bFirst && !bLast) {
    return kQuadrantVI;
  }

  bFirst = bLast;
  bLast = vt.IsLeft(kVector[6]);
  if(bFirst && !bLast) {
    return kQuadrantVII;
  }

  return kQuadrantVIII;
}